﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Castle.Core.Internal;
using DHJ.Cost.Models;
using DHJ.Cost.Models.Dto;
using DHJ.Cost.Report.Dto;
using DHJ.Cost.Reports;
using DHJ.Cost.SZ_Models.Dto;
using DHJ.Cost.Timing;
using Microsoft.EntityFrameworkCore;

namespace DHJ.Cost.SZ_Models
{
    public class ReportAppService : CostAppServiceBase, IReportAppService
    {
        private readonly IRepository<SzReport> _szReportRepository;
        private readonly IRepository<Model> _modelRepository;
        private readonly IRepository<ChReport> _chReportRepository;
        public ReportAppService(IRepository<SzReport> szReportRepository, IRepository<Model> modelRepository, IRepository<ChReport> chReportRepository)
        {
            _szReportRepository = szReportRepository;
            _modelRepository = modelRepository;
            _chReportRepository = chReportRepository;
        }



        public async Task<ListResultDto<SzReportListDto>> GetSzReports(GetSzReportsInput input)
        {

            List<Model> models = await GetModelList();

            var query = from sz in _szReportRepository.GetAll().Where(p => p.Time.Month <= input.Month && p.Time.Year <= input.Year)
                        join m in models on sz.ModelCode equals m.Code
                        select sz;
            var list = await query.GroupBy(e => e.ModelCode).Select(g => new SzReportListDto()
            {
                ActualCost = g.Select(p => p.ActualCost).FirstOrDefault(),
                ContractPrice = g.Select(p => p.ContractPrice).FirstOrDefault(),
                MaterialsPayment = g.Select(p => p.MaterialsPayment).FirstOrDefault(),
                ManagementCost = g.Select(p => p.ManagementCost).FirstOrDefault(),
                ModelCode = g.Key,
                OutsourcePayment = g.Select(p => p.OutsourcePayment).FirstOrDefault(),
                TemporaryPrice = g.Select(p => p.TemporaryPrice).FirstOrDefault(),
                TotalCost = g.Select(p => p.TotalCost).FirstOrDefault(),
                TotalSettlement = g.Select(p => p.TotalPayment).FirstOrDefault(),
                TotalPayment = g.Select(p => p.TotalPayment).FirstOrDefault(),
                TotalReceipts = g.Select(p => p.TotalReceipts).FirstOrDefault(),
                SettledCost = g.Select(p => p.SettledCost).FirstOrDefault()

            }).ToListAsync();


            foreach (var model in models)
            {
                if (!list.Any(e => e.ModelCode == model.Code))
                    list.Add(new SzReportListDto() { ModelCode = model.Code });
            }

            return new ListResultDto<SzReportListDto>(list);
        }

        public async Task<ListResultDto<ChReportListDto>> GetChReportList(GetChReportsInput input)
        {
            List<Model> models = await GetModelList();

            var query = from mh in _chReportRepository.GetAll().Where(p => p.Time.Month <= input.Month && p.Time.Year <= input.Year)
                        join m in models on mh.ModelCode equals m.Code
                        select mh;

            var list = await query.GroupBy(e => e.ModelCode).Select(g => new ChReportListDto()
            {
                ModelCode = g.Key,
                FuCaiCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.FuCaiCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.FuCaiCost),
                BiaoZhunJianCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.BiaoZhunJianCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.BiaoZhunJianCost),
                GongZhuangCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.GongZhuangCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.GongZhuangCost),

                QiTaCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.QiTaCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.QiTaCost),
                RanDongCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.RanDongCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.RanDongCost),
                RenGongCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.RenGongCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.RenGongCost),
                ZhiZaoCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.ZhiZaoCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.ZhiZaoCost),
                WaiXieCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.WaiXieCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.WaiXieCost),
                ZhuCaiCost = g.Where(p => p.Type == ChReportType.初始值).Select(p => p.ZhuCaiCost).FirstOrDefault() - g.Where(p => p.Type == ChReportType.月记录).Sum(p => p.ZhuCaiCost)
            }).ToListAsync();

            foreach (var model in models)
            {
                if (!list.Any(e => e.ModelCode == model.Code))
                    list.Add(new ChReportListDto() { ModelCode = model.Code });
            }


            return new ListResultDto<ChReportListDto>(list);
        }
        public async Task<List<Model>> GetModelList()
        {
            return await _modelRepository.GetAll().ToListAsync();
        }


        public async Task<List<SzReportEditDto>> GetSzReportForEdit()
        {

            List<SzReportEditDto> szReportEditlt = new List<SzReportEditDto>();
            var modellist = await GetModelList();
            foreach (var m in modellist)
            {
                SzReportEditDto edit = new SzReportEditDto
                {

                    ModelCode = m.Code
                };
                szReportEditlt.Add(edit);
            }

            return ObjectMapper.Map<List<SzReportEditDto>>(szReportEditlt);
        }

        public async Task CreatOrUpdateSzReport(GetSzReportEditInput input)
        {

            await CreatSzReport(input);

        }

        private async Task CreatSzReport(GetSzReportEditInput input)
        {
            foreach (var item in input.SzReportEditDtoList)
            {
                item.Time = new OccurrenceTime(input.Year, input.Month);

                var szReprot = await _szReportRepository
                    .FirstOrDefaultAsync(e => e.ModelCode == item.ModelCode && e.Time.Year == input.Year && e.Time.Month == input.Month);
                if (szReprot != null)
                {
                    var id = szReprot.Id;
                    ObjectMapper.Map(item, szReprot);
                    szReprot.Id = id;
                }
                else
                {
                    var report = ObjectMapper.Map<SzReport>(item);
                    await _szReportRepository.InsertAsync(report);
                }
            }
        }

        public async Task DeleteSzReport(EntityDto input)
        {
            await _szReportRepository.DeleteAsync(input.Id);
        }


        public async Task<List<ChReportEditDto>> GetChReportForEdit()
        {

            List<ChReportEditDto> chReportEditlt = new List<ChReportEditDto>();
            var modellist = await GetModelList();
            foreach (var m in modellist)
            {
                ChReportEditDto edit = new ChReportEditDto
                {

                    ModelCode = m.Code
                  
                };
                chReportEditlt.Add(edit);
            }

            return ObjectMapper.Map<List<ChReportEditDto>>(chReportEditlt);
        }

        public async Task CreatOrUpdateChReport(GetChReportEditInput input)
        {
            await CreatChReport(input);
        }

        private async Task CreatChReport(GetChReportEditInput input)
        {
            foreach (var item in input.ChReportEditDtoList)
            {
                item.Time = new OccurrenceTime(input.Year, input.Month);

                var chReprot = await _chReportRepository
                    .FirstOrDefaultAsync(e => e.ModelCode == item.ModelCode && e.Time.Year == input.Year && e.Time.Month == input.Month&&e.Type==item.Type);

                if (chReprot != null)
                {
                    var id = chReprot.Id;

                    ObjectMapper.Map(item, chReprot);

                    chReprot.Id = id;
                }
                else
                {
                    var report = ObjectMapper.Map<ChReport>(item);
                    await _chReportRepository.InsertAsync(report);
                }
            }
        }

        private async Task UpdateChReport(ChReportEditDto input)
        {
            var report = ObjectMapper.Map<ChReport>(input);
            await _chReportRepository.UpdateAsync(report);
        }

        public async Task DeleteChReport(int input)
        {
            await _chReportRepository.DeleteAsync(input);
        }
    }
}